/**
 * @TipManager.as
 *
 * @author sodaChen mail:sujun10#21cn.com
 * @version 1.0
 * <br>Copyright (C), 2014 FeiYin.com
 * <br>This program is protected by copyright laws.
 * <br>Program Name:Battle
 * <br>Date:2014-7-30
 */
package com.asframe.mgr
{
	import com.asframe.display.tip.ITip;
	import com.asframe.display.tip.ITipView;
	import com.asframe.display.tip.TextTipView;
	import com.asframe.display.tip.TipData;
	import com.asframe.display.tip.TipProxy;
	import com.asframe.pattern.Singleton;

	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.display.Stage;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.events.TimerEvent;
	import flash.geom.Rectangle;
	import flash.utils.Dictionary;
	import flash.utils.Timer;

	/**
	 * 基于鼠标事件的tip管理对象，支持自定义面板和设置默认面板
	 * @author sodaChen
	 * Date:2014-7-30
	 */
	public class TipsMgr extends Singleton
	{
		/** 默认的提示view对象 **/
		public var defaultView:ITipView;
		/** 活动窗口，指的是游戏窗口（舞台窗口） **/
		public var activeArea:Rectangle = new Rectangle(0, 0, 800, 600);
		/** X偏移值 **/
		public var offsetX:int = 15;
		/** Y偏移值 **/
		public var offsetY:int = 15;
		/** 默认延迟100毫秒 **/
		public var delayTime:int = 100;
		/** 舞台对象 **/
		private var stage:Stage;
		/** 存放提示内容的容器对象 **/
		private var tipContainer:Sprite;
		/** 当前活动的提示内容 **/
		private var currentTip:TipData;
		/** 计时器，主要是用于延迟鼠标事件的触发，防止误触发 **/
		private var timer:Timer;
		/**  **/
		private var tipDic:Dictionary = new Dictionary();
		/**  **/
		private var tipSpriteDic:Dictionary = new Dictionary();

		private static var instance:TipsMgr;

		public static function getInstance():TipsMgr
		{
			if(instance == null)
				instance = new TipsMgr();
			return instance;
		}
		private function onStageResize(evt:Event):void
		{
			//舞台变化，那么活动窗口也要变化(这里好像有可能会延迟，尺寸不一定正确，如果有问题，则需要增加延迟)
			activeArea.width = stage.stageWidth;
			activeArea.height = stage.stageHeight;
		}
		/**
		 * 初始化提示管理器
		 * @param tipContainer 提示的显示容器
		 * @param stage stage
		 * @param defaultView 默认的提示界面
		 *
		 */
		public function initTips(tipContainer:Sprite,stage:Stage,defaultView:ITipView = null):void
		{
			this.tipContainer = tipContainer;
			this.stage = stage;
			stage.addEventListener(Event.RESIZE,onStageResize);
			if(defaultView != null)
				this.defaultView = defaultView;

			activeArea.width = stage.stageWidth;
			activeArea.height = stage.stageHeight;

			//如果还是等于空，则生成一个默认的文本提示对象
			if(this.defaultView == null)
				this.defaultView = new TextTipView();
		}
		public function registerProxyTip(tipDisplay:DisplayObject,tipData:Object,tipView:ITipView = null):void
		{
			var tipProxy:TipProxy = new TipProxy();
			tipProxy.tipDisplay = tipDisplay;
			tipProxy.tip = tipData;
			if(tipView == null)
				tipView = defaultView;
			tipProxy.tipView = tipView;
			registerTip(tipProxy,tipView);
		}
		public function unregisterProxyTip(tipSprite:Sprite):void
		{
			unregisterTip(tipSprite);
		}
		/**
		 * 注册一个tip对象
		 * @param tip tipView实例,即需要提示的界面
		 * @param isAuto 是否自动相应3个鼠标事件，否则只会监听鼠标的移动事件，直接到手动删除
		 *
		 */
		public function registerTip(tip:*,tipView:*):void
		{
			var tipData:TipData = new TipData();
			var container:DisplayObject = null;

			if(tip is ITip)
			{
				tipData.tip = tip;
				container = tipData.tip.getContainer();
			}
			else if(tip is Sprite)
			{
				container = tip;
			}
			else
			{
				throw new Error("注册tip必须是基于Sprite或者ITip接口对象");
			}
			if(tipView is ITipView)
			{
				tipData.tipView = tipView;
				tipData.viewContainer = tipData.tipView.getContainer();
			}
			else if(tipView is Sprite)
			{
				tipData.viewContainer = tipView;
			}
			else
			{
				throw new Error("注册tipView必须是基于Sprite或者ITipView接口对象");
			}

			tipData.container = container;

			if(!stage.hasEventListener(MouseEvent.MOUSE_MOVE))
				stage.addEventListener(MouseEvent.MOUSE_MOVE,stageMouseMove);

			container.addEventListener(MouseEvent.ROLL_OVER, displayRollOver, false, 0, false);
			container.addEventListener(MouseEvent.ROLL_OUT, displayRollOut, false, 0, false);
			tipDic[container] = tipData;
		}
		public function unregisterTip(tip:*):void
		{
			var container:Sprite = null;
			if(tip is Sprite)
			{
				container = tip;
			}
			else if(tip is ITip)
			{
				container = tip.getContainer();
			}
			var tipData:TipData = tipDic[container];
			if(tipData != null)
			{
				container.removeEventListener(MouseEvent.ROLL_OVER, displayRollOver, false);
				container.removeEventListener(MouseEvent.ROLL_OUT, displayRollOut, false);
				if(currentTip == tip)
					currentTip == null;
			}
		}
		private function displayRollOver(event:MouseEvent) : void
		{
			currentTip = tipDic[event.currentTarget];
			if(currentTip == null)
				return ;
			closeTimer();
			openTimer();
		}

		private function displayRollOut(event:MouseEvent) : void
		{
			closeTimer();
			if (currentTip != null)
			{
				if(currentTip.tip != null)
					currentTip.tip.close();

				if(currentTip.viewContainer.parent == tipContainer)
					tipContainer.removeChild(currentTip.viewContainer);

				currentTip = null;
			}
		}
		private function stageMouseMove(event:MouseEvent) : void
		{
			if (currentTip != null)
			{
				var x:int = stage.mouseX + offsetX;
				var y:int = stage.mouseY + offsetY;
				var width:int = currentTip.viewContainer.width;
				var height:int = currentTip.viewContainer.height;
				if(currentTip.tipView != null)
				{
					width = currentTip.tipView.getWidth();
					height = currentTip.tipView.getHeight();
				}
				if (x < activeArea.left)
				{
					x = activeArea.left;
				}
				if (x + width > activeArea.right)
				{
					x = activeArea.right - width;
				}
				if (y < activeArea.top)
				{
					y = activeArea.top;
				}
				if (y + height > activeArea.bottom)
				{
					y = activeArea.bottom - height;
				}
				currentTip.viewContainer.x = x;
				currentTip.viewContainer.y = y;
			}
		}
		private function startTip(event:TimerEvent) : void
		{
			closeTimer();
			if (currentTip == null)
				return;

			if(currentTip.tip != null)
			{
				currentTip.tip.open();
			}
			//添加提示显示对象到tip容器上
			tipContainer.addChild(currentTip.viewContainer);
		}
		private function openTimer() : void
		{
			timer = new Timer(delayTime, 1);
			timer.addEventListener(TimerEvent.TIMER_COMPLETE, startTip);
			timer.start();
		}

		private function closeTimer() : void
		{
			if (timer && timer.running)
			{
				timer.reset();
				timer.removeEventListener(TimerEvent.TIMER_COMPLETE, startTip);
			}
		}
	}
}